
const db = require('../db/mysql')
const fs = require('fs');
const { STS } = require('ali-oss');
// const OSS = require('ali-oss');
var COS = require('cos-nodejs-sdk-v5');
const { ossConfig, cosConfig } = require('../config');
const getSTS = async () => {
    let sts = new STS({
     // 填写步骤1创建的RAM用户AccessKey。
     accessKeyId: 'LTAI5tRKjtS47kpvWq3w6mxU',
     accessKeySecret: 'XxEOPcW19XAFuYtUS7nalk6cSXsVm2'
   });
    // roleArn填写步骤2获取的角色ARN，例如acs:ram::175708322470****:role/ramtest。
    // policy填写自定义权限策略，用于进一步限制STS临时访问凭证的权限。如果不指定Policy，则返回的STS临时访问凭证默认拥有指定角色的所有权限。
    // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集。
    // expiration用于设置临时访问凭证有效时间单位为秒，最小值为900，最大值以当前角色设定的最大会话时间为准。本示例指定有效时间为3000秒。
    // sessionName用于自定义角色会话名称，用来区分不同的令牌，例如填写为sessiontest。
    let result = await sts.assumeRole('acs:ram::1636414426721760:role/ramosstest', ``, '3000', 'sessiontest')
    return {
        AccessKeyId: result.credentials.AccessKeyId,
        AccessKeySecret: result.credentials.AccessKeySecret,
        SecurityToken: result.credentials.SecurityToken,
        Expiration: result.credentials.Expiration
    }
};
const getOssCos = async function () {
    const config = {
        Bucket: cosConfig.Bucket, /* 填入您自己的存储桶，必须字段 */
        Region: cosConfig.Region,  /* 存储桶所在地域，例如 ap-beijing，必须字段 */
    }
    const token = await getSTS()
    // console.log(token, 'token');
    // const oss = new OSS({
    //     ...ossConfig,
    //     accessKeyId: token.AccessKeyId,
    //     accessKeySecret: token.AccessKeySecret,
    //     stsToken: token.SecurityToken,
    //     refreshSTSToken: async () => {
    //     // 向您搭建的STS服务获取临时访问凭证。
    //       const info = await getSTS();
    //       return {
    //         accessKeyId: info.AccessKeyId,
    //         accessKeySecret: info.AccessKeySecret,
    //         stsToken: info.SecurityToken
    //       }
    //     }
    // });
    const oss = new COS({
        SecretId: cosConfig.SecretId, // 推荐使用环境变量获取；用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
        SecretKey: cosConfig.SecretKey,
    });
    oss.get = (key, params = {}) => {
        return new Promise((resolve, reject) => {
            oss.getObjectUrl({
                ...config,
                Key: key,  /* 存储在桶里的对象键（例如1.jpg，a/b/test.txt），必须字段 */
                // Sign: true,
            }, function(err, data) {
                if (err && err!==null) return reject(err);
                /* 复制 downloadUrl 的值到浏览器打开会自动触发下载 */
                var url = data.Url + (data.Url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=inline;filename=' + key; // 补充强制下载的参数并重命名下载后的文件
                for (const k in params) {
                    if (params[k]) {
                        let tempKey = k[0].toLocaleUpperCase() + k.slice(1,);
                        url += '&'+tempKey+'='+params[k];
                    }
                }
                // console.log(err, data, 'get');
                data && resolve({ res: { ...data, url } })
            })
        })
    }
    oss.signatureUrl = (key, params = {}) => {
        return new Promise((resolve, reject) => {
            oss.get(key, params).then(res => {
                resolve((res && res.res && res.res.url) || {})
            }).catch(err => reject(err))
        })
    }
    oss.put = (key, file) => {
        return new Promise((resolve, reject) => {
            oss.putObject({
                ...config,
                Key: key,  /* 存储在桶里的对象键（例如1.jpg，a/b/test.txt），必须字段 */
                StorageClass: 'STANDARD',
                Body: fs.createReadStream(file), // 上传文件对象
                ContentLength: fs.statSync(file).size,
                onProgress: function(progressData) {
                    // console.log(JSON.stringify(progressData));
                }
            }, function(err, data) {
                // console.log(err, data, 'put');
                if (err && err!==null) return reject(err);
                data && resolve(data)
            })
        })
    }
    oss.deleteMulti = (keys, params = {}) => {
        return new Promise((resolve, reject) => {
            oss.deleteMultipleObject({
                ...config,
                ...params,
                Objects: keys
            }, function(err, data) {
                // console.log(err || data);
                if (err && err!==null) return reject(err);
                data && resolve(data)
            })
        })
    }
    return { token, oss }
}
const upload = async function ({ key, localFile }) {
    try {
        const { oss } = await getOssCos()
        // oss.put上传图片
        await oss.put(key, localFile);
    
        // 过期时间10分钟,图片处理式样"image/resize,w_300"。 , {expires: 600, 'process' : 'image/resize,w_300'}
        const signUrl = await oss.signatureUrl(key);
        // const url = `http://${ossConfig.bucket}.${ossConfig.endpoint}/${key}`
        const url = signUrl
        let sql = `INSERT INTO file(name, url, file_key) VALUES ('${key.split('.')[0]}', '${url.split('?')[0]}', '${key}')`
        await db.query(sql)
        // 删除本地储存的图片
        fs.unlinkSync(localFile);
        return url.split('?')[0]
    } catch(e) {
        console.error('error: upload %j', e);
        return Promise.reject(e)
    }
}

const getFiles = async function ({ name, currentPage = 1, pageSize = 10, sort = 'create_time.ASC' }) {
    try {
        let sql = `SELECT * from boycot.file where`;
        let query = `name like '%${name || ''}%' AND deleted = '0'`
        let orderby = `ORDER BY ${sort.split('.').join(' ')}`
        let limit = `LIMIT ${(currentPage - 1) * pageSize},${pageSize};`
        let res = await db.query([sql, query, orderby, limit].join(' '));
        let pageRes = await db.query(['SELECT COUNT(*) as recordCounts FROM boycot.file where', query].join(' '));
        let total = pageRes.results[0].recordCounts
        // 处理数据格式
        let records = await Promise.all(res.results.map(async el => {
            const { oss } = await getOssCos()
            let url = el.file_key || el.url.split('.com')[1].split('?')[0].replace(/\//g, '')
            let ossUrl = await oss.get(url)
            let signUrl = await oss.signatureUrl(url)
            let resizeUrl = await oss.signatureUrl(url, {expires: 3600, 'process' : `image/resize,p_${ossUrl.res.size > 1024 * 1024 ? '5': '10'}`})
            return { origionUrl: signUrl, url: resizeUrl, id: el.id, name: el.name, canDelete: el.can_delete > 0, createTime: el.create_time }
        }))
        return {
            total,
            currentPage: +currentPage,
            pageSize: +pageSize,
            records
        }
    } catch(e) {
        console.error('error: getFiles %j', e);
        return Promise.reject(e)
    }
}
const deleteFiles = async function ({ ids }) {
    try {
        const { oss } = await getOssCos()
        let items = await db.query(`SELECT * from boycot.file where id in (${ids.join(',')});`);
        // 1. 删除oss资源
        await oss.deleteMulti(items.results.map(el => ({ Key: el.file_key })), {quiet: true});
        let sql = `DELETE from boycot.file  where id in (${ids.join(',')});`
        // 2. 逻辑删除数据库
        // let sql = `UPDATE boycot.file SET deleted='1' where id in (${ids.join(',')});`
        await db.query(sql)
        return true
    } catch(e) {
        console.error('error: deleteFiles %j', e);
        return Promise.reject(e)
    }
}

const updateFiles = async function ({ id, name, url }) {
    try {
        // UPDATE boycot.file SET name='fav13',url='http://boycot.oss-cn-shenzhen.aliyuncs.com/fav.ico'  where id = 1;
        let sql = `UPDATE boycot.file SET name='${name}',url='${url}' where id = ${id};`;
        await db.query(sql);
        return true
    } catch(e) {
        console.error('error: updateFiles %j', e);
        return Promise.reject(e)
    }
}

module.exports = {
    upload,
    getFiles,
    deleteFiles,
    updateFiles
}